package net.mingsoft.flk.service.Impl;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.hazelcast.util.MD5Util;
import net.mingsoft.base.entity.ResultData;
import net.mingsoft.base.util.JSONObject;
import net.mingsoft.examine.utils.BlankUtil;
import net.mingsoft.flk.entity.FlkEncryption;
import net.mingsoft.flk.entity.vo.FlkRole;
import net.mingsoft.flk.enums.FlkType;
import net.mingsoft.flk.gmcryptojni.GMCryptoUtil;
import net.mingsoft.flk.mapper.FlkEncryptionMapper;
import net.mingsoft.flk.service.FlkEncryptionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.mingsoft.flk.util.FlkUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;

/**
 * <p>
 * 弗兰克加密内容 服务实现类
 * </p>
 *
 * @author 作者
 * @since 2023-03-10
 */
@Service
public class FlkEncryptionServiceImpl extends ServiceImpl<FlkEncryptionMapper, FlkEncryption> implements FlkEncryptionService {

    /**
     * 获取加密内容
     *
     * @param type       类型
     * @param businessId 业务id
     * @return obj
     */
    @Override
    public FlkEncryption getFlkEncryption(Integer type, String businessId) {
        QueryWrapper<FlkEncryption> wrapper = new QueryWrapper<>();
        wrapper.eq("type", type)
                .eq("business_id", businessId);
        return this.getOne(wrapper);
    }

    /**
     * 校验
     *
     * @param type       类型 1.用户 2.角色 3.日志
     * @param businessId 业务id
     * @param keyContent 当前原始内容
     * @return yn
     */
    @Override
    public ResultData verification(Integer type, String businessId, String keyContent) {
        try {
            return this.verification(type, businessId, keyContent, false);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultData.build().error("校验异常:" + e.getMessage());
        }
    }

    /**
     * 校验
     *
     * @param type       类型 1.用户 2.角色 3.日志
     * @param businessId 业务id
     * @param keyContent 当前原始内容
     * @param flag       是否提醒
     * @return yn
     */
    @Override
    public ResultData verification(Integer type, String businessId, String keyContent, boolean flag) {
        try {
            QueryWrapper<FlkEncryption> wrapper = new QueryWrapper<>();
            wrapper.eq("type", type)
                    .eq("business_id", businessId);
            if (flag) {
                wrapper.eq("remind", 0);
            }
            FlkEncryption flkEncryption = getOne(wrapper);
            if (BlankUtil.isBlank(flkEncryption)) {
                return ResultData.build().error("当前选中无加密内容");
            }
            boolean msg = FlkUtils.verification(keyContent, flkEncryption.getEncryptionKey());
            return msg ? ResultData.build().success("校验成功") : ResultData.build().error("数据已被修改,请联系管理员");
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultData.build().error("校验异常:" + e.getMessage());
        }
    }

    /**
     * 校验
     *
     * @param id id
     * @return yn
     */
    @Override
    public ResultData verification(Integer id, String content) {
        FlkEncryption encryption = this.getById(id);
        return this.verification(encryption.getType(), encryption.getBusinessId(), content, true);
    }

    /**
     * 提醒
     *
     * @param type       类型
     * @param businessId 业务id
     */
    @Override
    public void remind(Integer type, String businessId) {
        FlkEncryption encryption = this.getFlkEncryption(type, businessId);
        encryption.setRemind(1);
        this.updateById(encryption);
    }

    /**
     * 获取未提醒的
     *
     * @param type       类型
     * @param businessId 业务id
     * @return list
     */
    @Override
    public FlkEncryption noRemind(Integer type, String businessId) {
        QueryWrapper<FlkEncryption> wrapper = new QueryWrapper<>();
        wrapper.eq("type", type)
                .eq("business_id", businessId).eq("remind", 0);
        return this.getOne(wrapper);
    }

    /**
     * 添加
     *
     * @param type       类型
     * @param businessId 业务id
     * @param keyContent 内容
     * @return obj
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlkEncryption saveFlkEncryption(Integer type, String businessId, String keyContent) {
        FlkEncryption encryption = new FlkEncryption();
        String encryptionKey = FlkUtils.hmacSm3Msg(keyContent);
        encryption.setType(type).setBusinessId(businessId).setEncryptionKey(encryptionKey);
        this.save(encryption);
        return encryption;
    }

    /**
     * 修改
     *
     * @param type       类型
     * @param businessId 业务id
     * @param keyContent 内容
     * @return obj
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFlkEncryption(Integer type, String businessId, String keyContent) {
        GMCryptoUtil gmCryptoUtil = GMCryptoUtil.getInstance();
        FlkEncryption flkEncryption = this.getFlkEncryption(type, businessId);
        if (BlankUtil.isBlank(flkEncryption)) {
            FlkEncryption encryption = this.saveFlkEncryption(type, businessId, keyContent);
            return encryption != null;
        }
        String encryptionKey = FlkUtils.hmacSm3Msg(keyContent);
        UpdateWrapper<FlkEncryption> wrapper = new UpdateWrapper<>();
        wrapper.eq("type", type)
                .eq("business_id", businessId)
                .set("encryption_key", encryptionKey);
        return this.update(wrapper);
    }

    /**
     * 角色
     *
     * @param flag    y-修改 n-新增
     * @param flkRole 内容
     * @return obj
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlkEncryption saveRoleFlkEncryption(boolean flag, FlkRole flkRole) {
        GMCryptoUtil gmCryptoUtil = GMCryptoUtil.getInstance();
        FlkEncryption flkEncryption;
        String json = JSONObject.toJSONStringWithDateFormat(flkRole, "yyyy-MM-dd HH:mm:ss");
        String encryptionKey = FlkUtils.hmacSm3Msg(json);
        // 判断角色是否存在
        if (flag) {
            flkEncryption = this.getFlkEncryption(FlkType.ROLE.getCode(), String.valueOf(flkRole.getRoleBean().getId()));
            if (BlankUtil.isBlank(flkEncryption)) {
                this.saveFlkEncryption(FlkType.ROLE.getCode(), String.valueOf(flkRole.getRoleBean().getId()), encryptionKey);
            } else {
                this.updateFlkEncryption(FlkType.ROLE.getCode(), String.valueOf(flkRole.getRoleBean().getId()), encryptionKey);
            }
        } else {
            this.saveFlkEncryption(FlkType.ROLE.getCode(), String.valueOf(flkRole.getRoleBean().getId()), encryptionKey);
        }
        flkEncryption = this.getFlkEncryption(FlkType.ROLE.getCode(), String.valueOf(flkRole.getRoleBean().getId()));
        return flkEncryption;
    }


}
